home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / fileutil.13 / fileutil / fileutils-3.13 / src / mknod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-05  |  5.8 KB  |  230 lines

  1. /* mknod -- make special files
  2.    Copyright (C) 90, 91, 95, 1996 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software Foundation,
  16.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  17.  
  18. /* Usage: mknod [-m mode] [--mode=mode] path {bcu} major minor
  19.         make a block or character device node
  20.           mknod [-m mode] [--mode=mode] path p
  21.         make a FIFO (named pipe)
  22.  
  23.    Options:
  24.    -m, --mode=mode    Set the mode of created nodes to MODE, which is
  25.             symbolic as in chmod and uses the umask as a point of
  26.             departure.
  27.  
  28.    David MacKenzie <djm@ai.mit.edu>  */
  29.  
  30. #include <config.h>
  31. #include <stdio.h>
  32. #include <getopt.h>
  33. #include <sys/types.h>
  34.  
  35. #include "system.h"
  36. #include "modechange.h"
  37. #include "error.h"
  38. #include "xstrtol.h"
  39.  
  40. /* The name this program was run with. */
  41. char *program_name;
  42.  
  43. /* If nonzero, display usage information and exit.  */
  44. static int show_help;
  45.  
  46. /* If nonzero, print the version on standard output and exit.  */
  47. static int show_version;
  48.  
  49. static struct option const longopts[] =
  50. {
  51.   {"mode", required_argument, NULL, 'm'},
  52.   {"help", no_argument, &show_help, 1},
  53.   {"version", no_argument, &show_version, 1},
  54.   {NULL, 0, NULL, 0}
  55. };
  56.  
  57. static void
  58. usage (int status)
  59. {
  60.   if (status != 0)
  61.     fprintf (stderr, _("Try `%s --help' for more information.\n"),
  62.          program_name);
  63.   else
  64.     {
  65.       printf (_("Usage: %s [OPTION]... NAME TYPE [MAJOR MINOR]\n"), program_name);
  66.       printf (_("\
  67. Create the special file NAME of the given TYPE.\n\
  68. \n\
  69.   -m, --mode=MODE   set permission mode (as in chmod), not 0666 - umask\n\
  70.       --help        display this help and exit\n\
  71.       --version     output version information and exit\n\
  72. \n\
  73. MAJOR MINOR are forbidden for TYPE p, mandatory otherwise.  TYPE may be:\n\
  74. \n\
  75.   b      create a block (buffered) special file\n\
  76.   c, u   create a character (unbuffered) special file\n\
  77.   p      create a FIFO\n"));
  78.     }
  79.   exit (status);
  80. }
  81.  
  82. int
  83. main (int argc, char **argv)
  84. {
  85.   unsigned short newmode;
  86.   struct mode_change *change;
  87.   char *symbolic_mode;
  88.   int optc;
  89.   int i_major, i_minor;
  90.   long int tmp_major, tmp_minor;
  91.   char *s;
  92.  
  93.   program_name = argv[0];
  94.   setlocale (LC_ALL, "");
  95.   bindtextdomain (PACKAGE, LOCALEDIR);
  96.   textdomain (PACKAGE);
  97.  
  98.   symbolic_mode = NULL;
  99.  
  100.   while ((optc = getopt_long (argc, argv, "m:", longopts, (int *) 0)) != EOF)
  101.     {
  102.       switch (optc)
  103.     {
  104.     case 0:
  105.       break;
  106.     case 'm':
  107.       symbolic_mode = optarg;
  108.       break;
  109.     default:
  110.       usage (1);
  111.     }
  112.     }
  113.  
  114.   if (show_version)
  115.     {
  116.       printf ("mknod - %s\n", PACKAGE_VERSION);
  117.       exit (0);
  118.     }
  119.  
  120.   if (show_help)
  121.     usage (0);
  122.  
  123.   newmode = 0666 & ~umask (0);
  124.   if (symbolic_mode)
  125.     {
  126.       change = mode_compile (symbolic_mode, 0);
  127.       if (change == MODE_INVALID)
  128.     error (1, 0, _("invalid mode"));
  129.       else if (change == MODE_MEMORY_EXHAUSTED)
  130.     error (1, 0, _("virtual memory exhausted"));
  131.       newmode = mode_adjust (newmode, change);
  132.     }
  133.  
  134.   if (argc - optind != 2 && argc - optind != 4)
  135.     {
  136.       const char *msg;
  137.       if (argc - optind < 2)
  138.     msg = _("too few arguments");
  139.       else if (argc - optind > 4)
  140.     msg = _("too many arguments");
  141.       else
  142.     msg = _("wrong number of arguments");
  143.       error (0, 0, msg);
  144.       usage (1);
  145.     }
  146.  
  147.   /* Only check the first character, to allow mnemonic usage like
  148.      `mknod /dev/rst0 character 18 0'. */
  149.  
  150.   switch (argv[optind + 1][0])
  151.     {
  152.     case 'b':            /* `block' or `buffered' */
  153. #ifndef S_IFBLK
  154.       error (4, 0, _("block special files not supported"));
  155. #else
  156.       if (argc - optind != 4)
  157.     {
  158.       error (0, 0, _("\
  159. when creating block special files, major and minor device\n\
  160. numbers must be specified"));
  161.       usage (1);
  162.     }
  163.  
  164.       s = argv[optind + 2];
  165.       if (xstrtol (s, NULL, 0, &tmp_major, NULL) != LONGINT_OK)
  166.     error (1, 0, _("invalid major device number `%s'"), s);
  167.  
  168.       s = argv[optind + 3];
  169.       if (xstrtol (s, NULL, 0, &tmp_minor, NULL) != LONGINT_OK)
  170.     error (1, 0, _("invalid minor device number `%s'"), s);
  171.  
  172.       i_major = (int) tmp_major;
  173.       i_minor = (int) tmp_minor;
  174.  
  175.       if (mknod (argv[optind], newmode | S_IFBLK, makedev (i_major, i_minor)))
  176.     error (1, errno, "%s", argv[optind]);
  177. #endif
  178.       break;
  179.  
  180.     case 'c':            /* `character' */
  181.     case 'u':            /* `unbuffered' */
  182. #ifndef S_IFCHR
  183.       error (4, 0, _("character special files not supported"));
  184. #else
  185.       if (argc - optind != 4)
  186.     {
  187.       error (0, 0, _("\
  188. when creating character special files, major and minor device\n\
  189. numbers must be specified"));
  190.       usage (1);
  191.     }
  192.  
  193.       s = argv[optind + 2];
  194.       if (xstrtol (s, NULL, 0, &tmp_major, NULL) != LONGINT_OK)
  195.     error (1, 0, _("invalid major device number `%s'"), s);
  196.  
  197.       s = argv[optind + 3];
  198.       if (xstrtol (s, NULL, 0, &tmp_minor, NULL) != LONGINT_OK)
  199.     error (1, 0, _("invalid minor device number `%s'"), s);
  200.  
  201.       i_major = (int) tmp_major;
  202.       i_minor = (int) tmp_minor;
  203.  
  204.       if (mknod (argv[optind], newmode | S_IFCHR, makedev (i_major, i_minor)))
  205.     error (1, errno, "%s", argv[optind]);
  206. #endif
  207.       break;
  208.  
  209.     case 'p':            /* `pipe' */
  210. #ifndef S_ISFIFO
  211.       error (4, 0, _("fifo files not supported"));
  212. #else
  213.       if (argc - optind != 2)
  214.     {
  215.       error (0, 0, _("\
  216. major and minor device numbers may not be specified for fifo files"));
  217.       usage (1);
  218.     }
  219.       if (mkfifo (argv[optind], newmode))
  220.     error (1, errno, "%s", argv[optind]);
  221. #endif
  222.       break;
  223.  
  224.     default:
  225.       usage (1);
  226.     }
  227.  
  228.   exit (0);
  229. }
  230.